package com.gary.spring;

import com.gary.spring.bean.Bean1;
import com.gary.spring.bean.Bean2;
import com.gary.spring.bean.Bean3;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import javax.management.StandardEmitterMBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author peng_rui
 * @date 2022/6/22
 */
public class DigInAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2());
        beanFactory.registerSingleton("bean3", new Bean3());
        //@Value
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //${} 解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        // 1. 查找哪些属性、方法加了@Autowired @Value , 这里称之为InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
        //执行依赖注入 @Autowired @Value
        processor.postProcessProperties(null, bean1, "bean1");
        System.out.println(bean1);

//        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
//        findAutowiringMetadata.setAccessible(true);
//        InjectionMetadata injectionMetadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
//        System.out.println(injectionMetadata);
//        System.out.println("**************");
//        System.out.println(bean1);
//        injectionMetadata.inject(bean1, "bean1", null);
//        System.out.println(bean1);

//        Method autoBean2 = Bean1.class.getDeclaredMethod("autoBean2", Bean2.class);
//        autoBean2.setAccessible(true);
//        DependencyDescriptor dd1 = new DependencyDescriptor(new MethodParameter(autoBean2, 0), false);
//        Object o = beanFactory.doResolveDependency(dd1, null, null, null);
//        System.out.println(o);
    }
}
